#!/usr/bin/python
#+------------------------------------------------------------------------------
#|
#| FILENAME: graph.pm
#|
#| PROJECT: Cairo Libraries
#|
#| FILE DESCRIPTION:
#|    This file contains an implementation of the base graph from which
#|    all other graphs are derived.
#|
#+------------------------------------------------------------------------------
#|
#| Cairolib is a series of extensions, examples, and libraries for the
#| Cairo graphics package (see http://www.cairographics.org).
#| 
#| Copyright (C) 2006  Bradford Elliott
#|
#| This library is free software; you can redistribute it and/or
#| modify it under the terms of the GNU Lesser General Public
#| License as published by the Free Software Foundation; either
#| version 2.1 of the License, or (at your option) any later version.
#| 
#| This library is distributed in the hope that it will be useful,
#| but WITHOUT ANY WARRANTY; without even the implied warranty of
#| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#| Lesser General Public License for more details.
#| 
#| You should have received a copy of the GNU Lesser General Public
#| License along with this library; if not, write to the Free Software
#| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
#| 
#+------------------------------------------------------------------------------
package cairolib::graph;

use strict;
use warnings;
use cairolib::cairointf;
use POSIX qw(ceil floor);
 
our @ISA = ('');

#+-----------------------------------------------------------------------------
#|
#| NAME:
#|    new()
#|
#| SYNOPSIS:
#|    new($width, $height);
#|
#| PARAMETERS:
#|    $width  (I) - The width of the graph to be created.
#|    $height (I) - The height of the graph to be created.
#|
#| FUNCTION:
#|    This is the constructor for the graph class which is used to construct
#|    a new graph object.
#|
#| RETURNS:
#|    Reference to the class object.
#|
#| NOTES:
#|    None.
#|
#+-----------------------------------------------------------------------------
sub new
{
    my $that = shift;
    my $class = ref($that) || $that;
    
    my $graph = undef;
    my $width  = $_[0];
    my $height = $_[1];
    
    my $leftGraph   = 100;
    my $rightGraph  = $width + $leftGraph;
    my $topGraph    = 40;
    my $bottomGraph = $topGraph + $height;
    
    #$width  += 100;
    #$height += 40;
    
    my %datasets;
    my %xaxisParams;
    my %yaxisParams;
    my $self = {GRAPH    => \$graph,
                WIDTH    => \$width,
                HEIGHT   => \$height,
                LEFT     => \$leftGraph,
                RIGHT    => \$rightGraph,
                TOP      => \$topGraph,
                BOTTOM   => \$bottomGraph,
                DATASETS => \%datasets,
                XAXIS    => \%xaxisParams,
                YAXIS    => \%yaxisParams};
    
    bless($self, $class);
    
    $self->init();
    
    return $self;
}


#+-----------------------------------------------------------------------------
#|
#| NAME:
#|    DESTROY()
#|
#| SYNOPSIS:
#|    DESTROY()
#|
#| PARAMETERS:
#|    None.
#|
#| FUNCTION:
#|    This is the destructor for the graph class. It is called
#|    automatically by perl when the instance of the class is no longer
#|    required.
#|
#| RETURNS:
#|    None.
#|
#| NOTES:
#|    None.
#|
#+-----------------------------------------------------------------------------
sub DESTROY
{
    my $self = shift;
}


#+-----------------------------------------------------------------------------
#|
#| NAME:
#|    init()
#|
#| SYNOPSIS:
#|    init()
#|
#| PARAMETERS:
#|    None.
#|
#| FUNCTION:
#|    This is the main initializer for the graph class.
#|
#| RETURNS:
#|    None.
#|
#| NOTES:
#|    None.
#|
#+-----------------------------------------------------------------------------
sub init
{
    my $self = shift;
    
    $self->{GRAPH} = new cairolib::cairointf(
                        ${$self->{WIDTH}} + 200,
                        ${$self->{HEIGHT}} + 80);
}


#+-----------------------------------------------------------------------------
#|
#| NAME:
#|    addDataSet()
#|
#| PARAMETERS:
#|    
#|
#| FUNCTION:
#|    
#|
#| RETURNS:
#|    
#|
#+-----------------------------------------------------------------------------
sub addDataSet
{
    my $self = shift;
   
    my $dataset = $_[0];
    my $name    = $_[1];
    my $color   = $_[2];
    
    $self->{DATASETS}{"$name"}{"color"} = $color;
    
    foreach my $element (keys(%$dataset))
    {
        $self->{DATASETS}{"$name"}{"data"}{$element} = $dataset->{$element};
    }
}


#+-----------------------------------------------------------------------------
#|
#| NAME:
#|    getMaxXCoordiate()
#|
#| PARAMETERS:
#|    
#|
#| FUNCTION:
#|    
#|
#| RETURNS:
#|    
#|
#+-----------------------------------------------------------------------------
sub getMaxXCoordiate
{
    my $self = shift;
    
    my $maxX = 0;
    
    foreach my $dataset (keys(%{$self->{DATASETS}}))
    {
        foreach my $key (keys(%{$self->{DATASETS}{$dataset}{"data"}}))
        {
            if($key > $maxX)
            {
                $maxX = $key;
            }
        }
    }
    
    if(1 == $self->{XAXIS}{"autoscale"})
    {
        $maxX = (ceil($maxX / 10.0))*10;
    }
    
    return $maxX;
}


#+-----------------------------------------------------------------------------
#|
#| NAME:
#|    getMaxYCoordinate()
#|
#| PARAMETERS:
#|    
#|
#| FUNCTION:
#|    
#|
#| RETURNS:
#|    
#|
#+-----------------------------------------------------------------------------
sub getMaxYCoordinate
{
    my $self = shift;
    my $maxY = 0;
    
    foreach my $dataset (keys(%{$self->{DATASETS}}))
    {
        foreach my $key (keys(%{$self->{DATASETS}{$dataset}{"data"}}))
        {
            my $value = $self->{DATASETS}{$dataset}{"data"}{$key};
            
            if($value > $maxY)
            {
                $maxY = $value;
            }
        }
    }
    
    $maxY = (ceil($maxY / 10.0))*10;
}


#+-----------------------------------------------------------------------------
#|
#| NAME:
#|    setXAxis()
#|
#| PARAMETERS:
#|    
#|
#| FUNCTION:
#|    
#|
#| RETURNS:
#|    
#|
#+-----------------------------------------------------------------------------
sub setXAxis
{
    my $self = shift;
    
    my ($label, $color, $min, $max, $increment) = @_;
    
    $self->{XAXIS}{"label"}     = $label;
    $self->{XAXIS}{"min"}       = $min;
    $self->{XAXIS}{"max"}       = $max;
    $self->{XAXIS}{"increment"} = $increment;
    $self->{XAXIS}{"color"}     = $color;
    $self->{XAXIS}{"autoscale"} = 1;
}


#+-----------------------------------------------------------------------------
#|
#| NAME:
#|    setYAxis()
#|
#| PARAMETERS:
#|    
#|
#| FUNCTION:
#|    
#|
#| RETURNS:
#|    
#|
#+-----------------------------------------------------------------------------
sub setYAxis
{
    my $self = shift;
    
    my ($label, $color, $min, $max, $increment) = @_;
    
    $self->{YAXIS}{"label"}     = $label;
    $self->{YAXIS}{"min"}       = $min;
    $self->{YAXIS}{"max"}       = $max;
    $self->{YAXIS}{"increment"} = $increment;
    $self->{YAXIS}{"color"}     = $color;
}


#+-----------------------------------------------------------------------------
#|
#| NAME:
#|    drawGraph()
#|
#| PARAMETERS:
#|    
#|
#| FUNCTION:
#|    
#|
#| RETURNS:
#|    
#|
#+-----------------------------------------------------------------------------
sub drawGraph
{
    my $self = shift;
    
    my $graph = $self->{GRAPH};
    
    my $left   = ${$self->{LEFT}};
    my $top    = ${$self->{TOP}};
    my $width  = ${$self->{WIDTH}};
    my $height = ${$self->{HEIGHT}};
    
    $graph->drawRect({"x" => $left,
                      "y" => $top,
                      "width" => $width,
                      "height" => $height,
                      "background-color" => "#FFFFFF",
                      "line-color" => "#000000"});
}


1

